package com.train.forum.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.train.forum.pojo.enums.ResponseEnum;
import com.train.forum.utils.R;
import com.train.forum.utils.Rs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 常见异常处理程序
 *
 * @author mek
 * @date 2023/6/13
 */
@Slf4j
@RestControllerAdvice
public class RRExceptionHandler {


    /**
     * <1> 处理 form data方式调用接口校验失败抛出的异常
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public R bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        Map<String, String> errorMap = new HashMap<>();
        fieldErrors.forEach((fieldError)->{
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        });
        log.error("bindExceptionHandler ERROR:",e);
        String msg=errorMap.values().stream().collect(Collectors.joining(","));
        return Rs.error(ResponseEnum.BIND_EXCEPTION.getCode(), msg).setData(errorMap);
    }
    /**
     * <2>方法参数验证校验异常拦截
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R exceptionHandle(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        Map<String, String> errorMap = new HashMap<>();
        fieldErrors.forEach((fieldError)->{
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        });
        log.error("exceptionHandle ERROR:",e);

        String msg=errorMap.values().stream().collect(Collectors.joining(","));
        return Rs.error(ResponseEnum.METHOD_ARGUMENT_NOT_VALID_EXCEPTION.getCode(), msg).setData(errorMap);
    }


    /**
     * <4> 自定义异常处理
     * @param businessException
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    public R customHandler(BusinessException businessException){
        log.error("customHandler ERROR:",businessException.getMsg());
        return Rs.error(businessException.code,businessException.getMsg());
    }

    /**
     * <5> 其他所有异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R exceptionHandler(Exception e){
        log.error("ExceptionControllerAdvice.exceptionHandler.exceptionHandler==================",e);
        return Rs.error(ResponseEnum.SERVER_INTERNAL_ERROR.getCode(),e.getMessage());
    }

    //Sa-Token 全局异常拦截（拦截项目中的NotPermissionException异常）
    @ExceptionHandler(NotPermissionException.class)
    public R notPermissionException(NotPermissionException npe){
        log.error("ExceptionControllerAdvice.exceptionHandler.customHandler==================",npe);
        return Rs.error(ResponseEnum.NO_PERMISSION.getCode(),ResponseEnum.NO_PERMISSION.getMessage());
    }

    //Sa-Token 全局异常拦截（拦截项目中的NotLoginException异常）
    @ExceptionHandler(NotLoginException.class)
    public R handlerNotLoginException(NotLoginException nle){
        // 判断场景值，定制化异常信息
        String message = "";
        if(nle.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "未提供token";
        }
        else if(nle.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "检查到未登录，请先登录！";
        }
        else if(nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "账号已过期，请重新登录";
        }
        else if(nle.getType().equals(NotLoginException.BE_REPLACED)) {
            message = "账号在其他地方登录，你已经被顶下线了！";
        }
        else if(nle.getType().equals(NotLoginException.KICK_OUT)) {
            message = "账号存在异常，你已经被强制退出！";
        }
        else {
            message = "请先登录！";
        }
        // 返回给前端
        return Rs.error(ResponseEnum.NOT_LOGIN.getCode(),message);
    }

    //Sa-Token 全局异常拦截（拦截项目中的NotRoleException异常）
    @ExceptionHandler(NotRoleException.class)
    public R notRoleException(NotRoleException nle){
        // 判断场景值，定制化异常信息
        String message = "操作失败，没有权限";

        // 返回给前端
        return Rs.error(ResponseEnum.NO_PERMISSION.getCode(),message);
    }

}
